﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.IO;
using System.Text;
using System.Globalization;
using System.Text.RegularExpressions;

namespace NJA.FtpTestTool
{

    /// <summary>
    /// Enum FileListStyle
    /// </summary>
    public enum FileListStyle
    {
        /// <summary>
        /// The unix style
        /// </summary>
        UnixStyle,

        /// <summary>
        /// The windows style
        /// </summary>
        WindowsStyle,

        /// <summary>
        /// The unknown
        /// </summary>
        Unknown
    }
    #region 文件信息结构
    /// <summary>
    /// FTP处理操作类
    /// 功能：
    /// 下载文件
    /// 上传文件
    /// 上传文件的进度信息
    /// 下载文件的进度信息
    /// 删除文件
    /// 列出文件
    /// 列出目录
    /// 进入子目录
    /// 退出当前目录返回上一层目录
    /// 判断远程文件是否存在
    /// 判断远程文件是否存在
    /// 删除远程文件
    /// 建立目录
    /// 删除目录
    /// 文件（目录）改名
    /// </summary>
    public struct FileStruct
    {
        /// <summary>
        /// The flags
        /// </summary>
        public string Flags;

        /// <summary>
        /// The owner
        /// </summary>
        public string Owner;

        /// <summary>
        /// The group
        /// </summary>
        public string Group;

        /// <summary>
        /// The is directory
        /// </summary>
        public bool IsDirectory;

        /// <summary>
        /// The create time
        /// </summary>
        public DateTime CreateTime;

        /// <summary>
        /// The name
        /// </summary>
        public string Name;
        /// <summary>
        /// 文件大小
        /// </summary>
        public int FileSize;
    }
    #endregion
    /// <summary>
    /// Class ClsFTP.
    /// </summary>
    public class ClsFtp
    {
        /// <summary>
        /// FTP请求对象
        /// </summary>
        private FtpWebRequest request;

        /// <summary>
        /// FTP响应对象
        /// </summary>
        private FtpWebResponse response;

        /// <summary>
        /// FTP服务器地址
        /// </summary>
        private Uri myUri;

        /// <summary>
        /// 当前工作目录
        /// </summary>
        private string directoryPath;

        /// <summary>
        /// FTP登录用户
        /// </summary>
        private string userName;

        /// <summary>
        /// 错误信息
        /// </summary>
        private string errorMsg;

        /// <summary>
        /// FTP登录密码
        /// </summary>
        private string password;

        /// <summary>
        /// 连接FTP服务器的代理服务
        /// </summary>
        private WebProxy myProxy;

        /// <summary>
        /// 是否需要删除临时文件
        /// </summary>
        private bool isDeleteTempFile;

        /// <summary>
        /// 异步上传所临时生成的文件
        /// </summary>
        private string strUploadTempFile = string.Empty;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="ftpUri">FTP地址</param>
        /// <param name="strUserName">登录用户名</param>
        /// <param name="strPassword">登录密码</param>
        /// <param name="objProxy">连接代理</param>
        public ClsFtp(Uri ftpUri, string strUserName, string strPassword, WebProxy objProxy)
        {
            this.myUri = new Uri(ftpUri.GetLeftPart(UriPartial.Authority));
            directoryPath = ftpUri.AbsolutePath;
            if (!directoryPath.EndsWith("/"))
            {
                directoryPath += "/";
            }

            this.userName = strUserName;
            this.password = strPassword;
            this.myProxy = objProxy;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public ClsFtp()
        {
            this.userName = "anonymous";
            this.password = "@anonymous";
            this.myUri = null;
            this.myProxy = null;
        }

        #region 构造析构函数

        /// <summary>
        /// Initializes a new instance of the <see cref="ClsFtp"/> class.
        /// </summary>
        /// <param name="ftpUri">The FTP URI.</param>
        /// <param name="strUserName">Name of the string user.</param>
        /// <param name="strPassword">The string password.</param>
        public ClsFtp(Uri ftpUri, string strUserName, string strPassword)
        {
            this.myUri = new Uri(ftpUri.GetLeftPart(UriPartial.Authority));
            directoryPath = ftpUri.AbsolutePath;
            if (!directoryPath.EndsWith("/"))
            {
                directoryPath += "/";
            }

            this.userName = strUserName;
            this.password = strPassword;
            this.myProxy = null;
        }

        /// <summary>
        /// Finalizes an instance of the <see cref="ClsFtp"/> class.
        /// </summary>
        ~ClsFtp()
        {
            if (response != null)
            {
                response.Close();
                response = null;
            }

            if (request != null)
            {
                request.Abort();
                request = null;
            }
        }

        #endregion

        /// <summary>
        /// Delegate De_DownloadProgressChanged
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="DownloadProgressChangedEventArgs"/> instance containing the event data.</param>
        public delegate void DeDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e);

        /// <summary>
        /// Delegate De_DownloadDataCompleted
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.ComponentModel.AsyncCompletedEventArgs"/> instance containing the event data.</param>
        public delegate void DeDownloadDataCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e);

        /// <summary>
        /// Delegate De_UploadProgressChanged
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="UploadProgressChangedEventArgs"/> instance containing the event data.</param>
        public delegate void DeUploadProgressChanged(object sender, UploadProgressChangedEventArgs e);

        /// <summary>
        /// Delegate De_UploadFileCompleted
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="UploadFileCompletedEventArgs"/> instance containing the event data.</param>
        public delegate void DeUploadFileCompleted(object sender, UploadFileCompletedEventArgs e);
        #region 事件

        /// <summary>
        /// 异步下载进度发生改变触发的事件
        /// </summary>
        public event DeDownloadProgressChanged DownloadProgressChanged;

        /// <summary>
        /// 异步下载文件完成之后触发的事件
        /// </summary>
        public event DeDownloadDataCompleted DownloadDataCompleted;

        /// <summary>
        /// 异步上传进度发生改变触发的事件
        /// </summary>
        public event DeUploadProgressChanged UploadProgressChanged;

        /// <summary>
        /// 异步上传文件完成之后触发的事件
        /// </summary>
        public event DeUploadFileCompleted UploadFileCompleted;

        #endregion
        #region 属性信息

        /// <summary>
        /// FTP服务器地址
        /// </summary>
        public Uri Uri
        {
            get
            {
                if (this.directoryPath == "/")
                {
                    return this.myUri;
                }
                else
                {
                    string strUri = this.myUri.ToString();
                    if (strUri.EndsWith("/"))
                    {
                        strUri = strUri.Substring(0, strUri.Length - 1);
                    }

                    return new Uri(strUri + this.DirectoryPath);
                }
            }

            set
            {
                if (value.Scheme != Uri.UriSchemeFtp)
                {
                    throw new Exception("Ftp 地址格式错误!");
                }

                this.myUri = new Uri(value.GetLeftPart(UriPartial.Authority));
                this.directoryPath = value.AbsolutePath;
                if (!this.directoryPath.EndsWith("/"))
                {
                    this.directoryPath += "/";
                }
            }
        }

        /// <summary>
        /// 当前工作目录
        /// </summary>
        public string DirectoryPath
        {
            get
            {
                return directoryPath;
            }

            set
            {
                directoryPath = value;
            }
        }

        /// <summary>
        /// FTP登录用户
        /// </summary>
        public string UserName
        {
            get
            {
                return userName;
            }

            set
            {
                userName = value;
            }
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMsg
        {
            get
            {
                return errorMsg;
            }

            set
            {
                errorMsg = value;
            }
        }

        /// <summary>
        /// FTP登录密码
        /// </summary>
        public string Password
        {
            get
            {
                return password;
            }

            set
            {
                password = value;
            }
        }

        /// <summary>
        /// 连接FTP服务器的代理服务
        /// </summary>
        public WebProxy Proxy
        {
            get
            {
                return myProxy;
            }

            set
            {
                myProxy = value;
            }
        }

        #endregion

        #region 下载文件

        /// <summary>
        /// 从FTP服务器下载文件，使用与远程文件同名的文件名来保存文件
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <param name="localPath">本地路径</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public bool DownloadFile(string remoteFileName, string localPath)
        {
            return DownloadFile(remoteFileName, localPath, remoteFileName);
        }

        /// <summary>
        /// 从FTP服务器下载文件，指定本地路径和本地文件名
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <param name="localPath">本地路径</param>
        /// <param name="localFileName">保存本地的文件名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">
        /// 非法文件名或目录名!
        /// or
        /// 本地文件路径不存在!
        /// or
        /// 当前路径下已经存在同名文件！
        /// </exception>
        public bool DownloadFile(string remoteFileName, string localPath, string localFileName)
        {
            byte[] bt = null;
            try
            {
                if (!IsValidFileChars(remoteFileName) || !IsValidFileChars(localFileName)
                                                      || !IsValidPathChars(localPath))
                {
                    throw new Exception("非法文件名或目录名!");
                }

                if (!Directory.Exists(localPath))
                {
                    throw new Exception("本地文件路径不存在!");
                }

                string localFullPath = Path.Combine(localPath, localFileName);
                if (File.Exists(localFullPath))
                {
                    throw new Exception("当前路径下已经存在同名文件！");
                }

                bt = DownloadFile(remoteFileName);
                if (bt != null)
                {
                    FileStream stream = new FileStream(localFullPath, FileMode.Create);
                    stream.Write(bt, 0, bt.Length);
                    stream.Flush();
                    stream.Close();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 从FTP服务器下载文件，返回文件二进制数据
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <returns>System.Byte[].</returns>
        /// <exception cref="Exception">非法文件名或目录名!</exception>
        public byte[] DownloadFile(string remoteFileName)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName))
                {
                    throw new Exception("非法文件名或目录名!");
                }

                response = Open(new Uri(this.Uri.ToString() + remoteFileName), WebRequestMethods.Ftp.DownloadFile);
                Stream reader = response.GetResponseStream();

                MemoryStream mem = new MemoryStream(1024 * 500);
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                int totalByteRead = 0;
                while (true)
                {
                    bytesRead = reader.Read(buffer, 0, buffer.Length);
                    totalByteRead += bytesRead;
                    if (bytesRead == 0)
                        break;
                    mem.Write(buffer, 0, bytesRead);
                }

                if (mem.Length > 0)
                {
                    return mem.ToArray();
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 从FTP服务器下载文件，返回文件二进制数据
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <returns>System.Byte[].</returns>
        /// <exception cref="Exception">非法文件名或目录名!</exception>
        public byte[] DownloadFileByUrl(string remoteUrl)
        {
            try
            {
                response = Open(new Uri(remoteUrl), WebRequestMethods.Ftp.DownloadFile);
                Stream reader = response.GetResponseStream();

                MemoryStream mem = new MemoryStream(1024 * 500);
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                int totalByteRead = 0;
                while (true)
                {
                    bytesRead = reader.Read(buffer, 0, buffer.Length);
                    totalByteRead += bytesRead;
                    if (bytesRead == 0)
                        break;
                    mem.Write(buffer, 0, bytesRead);
                }

                if (mem.Length > 0)
                {
                    return mem.ToArray();
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        #endregion

        #region 异步下载文件

        /// <summary>
        /// 从FTP服务器异步下载文件，指定本地路径和本地文件名
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>        
        /// <param name="localPath">保存文件的本地路径,后面带有"\"</param>
        /// <param name="localFileName">保存本地的文件名</param>
        public void DownloadFileAsync(string remoteFileName, string localPath, string localFileName)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName) || !IsValidFileChars(localFileName)
                                                      || !IsValidPathChars(localPath))
                {
                    throw new Exception("非法文件名或目录名!");
                }

                if (!Directory.Exists(localPath))
                {
                    throw new Exception("本地文件路径不存在!");
                }

                string localFullPath = Path.Combine(localPath, localFileName);
                if (File.Exists(localFullPath))
                {
                    throw new Exception("当前路径下已经存在同名文件！");
                }

                DownloadFileAsync(remoteFileName, localFullPath);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 从FTP服务器异步下载文件，指定本地完整路径文件名
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <param name="localFullPath">本地完整路径文件名</param>
        public void DownloadFileAsync(string remoteFileName, string localFullPath)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName))
                {
                    throw new Exception("非法文件名或目录名!");
                }

                if (File.Exists(localFullPath))
                {
                    throw new Exception("当前路径下已经存在同名文件！");
                }

                MyWebClient client = new MyWebClient();

                client.DownloadProgressChanged +=
                    new DownloadProgressChangedEventHandler(this.ClientDownloadProgressChanged);
                client.DownloadFileCompleted +=
                    new System.ComponentModel.AsyncCompletedEventHandler(this.ClientDownloadFileCompleted);
                client.Credentials = new NetworkCredential(this.UserName, this.Password);
                if (this.Proxy != null)
                {
                    client.Proxy = this.Proxy;
                }

                client.DownloadFileAsync(new Uri(this.Uri.ToString() + remoteFileName), localFullPath);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 异步下载文件完成之后触发的事件
        /// </summary>
        /// <param name="sender">下载对象</param>
        /// <param name="e">数据信息对象</param>
        public void ClientDownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (DownloadDataCompleted != null)
            {
                DownloadDataCompleted(sender, e);
            }
        }

        /// <summary>
        /// 异步下载进度发生改变触发的事件
        /// </summary>
        /// <param name="sender">下载对象</param>
        /// <param name="e">进度信息对象</param>
        public void ClientDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (DownloadProgressChanged != null)
            {
                DownloadProgressChanged(sender, e);
            }
        }

        #endregion

        #region 上传文件

        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public bool UploadFile(string localFullPath)
        {
            return UploadFile(localFullPath, Path.GetFileName(localFullPath), false);
        }

        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件</param>
        /// <param name="overWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public bool UploadFile(string localFullPath, bool overWriteRemoteFile)
        {
            return UploadFile(localFullPath, Path.GetFileName(localFullPath), overWriteRemoteFile);
        }

        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public bool UploadFile(string localFullPath, string remoteFileName)
        {
            return UploadFile(localFullPath, remoteFileName, false);
        }

        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件名</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        /// <param name="overWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">
        /// 非法文件名或目录名!
        /// or
        /// 本地文件不存在!
        /// </exception>
        public bool UploadFile(string localFullPath, string remoteFileName, bool overWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName) || !IsValidFileChars(Path.GetFileName(localFullPath))
                                                      || !IsValidPathChars(Path.GetDirectoryName(localFullPath)))
                {
                    throw new Exception("非法文件名或目录名!");
                }

                if (File.Exists(localFullPath))
                {
                    FileStream stream = new FileStream(localFullPath, FileMode.Open, FileAccess.Read);
                    byte[] bt = new byte[stream.Length];
                    stream.Read(bt, 0, (Int32)stream.Length); ////注意，因为Int32的最大限制，最大上传文件只能是大约2G多一点
                    stream.Close();
                    return UploadFile(bt, remoteFileName, overWriteRemoteFile);
                }
                else
                {
                    throw new Exception("本地文件不存在!");
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="fileBytes">上传的二进制数据</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">非法文件名或目录名!</exception>
        public bool UploadFile(byte[] fileBytes, string remoteFileName)
        {
            if (!IsValidFileChars(remoteFileName))
            {
                throw new FtpException("非法文件名或目录名!");
            }

            return UploadFile(fileBytes, remoteFileName, false);
        }

        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="fileBytes">文件二进制内容</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        /// <param name="overWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">
        /// 非法文件名！
        /// or
        /// FTP服务上面已经存在同名文件！
        /// </exception>
        public bool UploadFile(byte[] fileBytes, string remoteFileName, bool overWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName))
                {
                    throw new FtpException("非法文件名！");
                }

                if (!overWriteRemoteFile && FileExist(remoteFileName))
                {
                    throw new FtpException("FTP服务上面已经存在同名文件！");
                }

                int errNum = 0;
                while (true)
                {//失败重试三次
                    try
                    {
                        try
                        {
                            request = (FtpWebRequest)WebRequest.Create(new Uri(this.Uri.ToString() + remoteFileName));
                            request.Method = WebRequestMethods.Ftp.UploadFile;
                            request.UseBinary = true;
                            request.Credentials = new NetworkCredential(this.UserName, this.Password);
                            request.ContentLength = fileBytes.Length;
                            if (this.Proxy != null)
                            {
                                request.Proxy = this.Proxy;
                            }

                        }
                        catch (WebException ep)
                        {
                            ErrorMsg = ep.ToString();
                            throw ep;
                        }
                        Stream requestStream = request.GetRequestStream();
                        using (MemoryStream mem = new MemoryStream(fileBytes))
                        {

                            byte[] buffer = new byte[1024];
                            int bytesRead = 0;
                            int totalRead = 0;
                            while (true)
                            {
                                bytesRead = mem.Read(buffer, 0, buffer.Length);
                                if (bytesRead == 0)
                                    break;
                                totalRead += bytesRead;
                                requestStream.Write(buffer, 0, bytesRead);
                            }

                            requestStream.Close();
                            response = (FtpWebResponse)request.GetResponse();
                            mem.Close();
                            mem.Dispose();
                            fileBytes = null;
                            return true;
                        }

                    }
                    catch (WebException ex)
                    {
                        errNum++;
                        if (errNum >= 3)
                        {
                            ErrorMsg = ex.ToString();
                            throw new FtpException(ex);
                        }
                    }
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw new FtpException(ep);
            }
        }

        #endregion

        #region 异步上传文件

        /// <summary>
        /// 异步上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件名</param>
        public void UploadFileAsync(string localFullPath)
        {
            UploadFileAsync(localFullPath, Path.GetFileName(localFullPath), false);
        }

        /// <summary>
        /// 异步上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件</param>
        /// <param name="overWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param>
        public void UploadFileAsync(string localFullPath, bool overWriteRemoteFile)
        {
            UploadFileAsync(localFullPath, Path.GetFileName(localFullPath), overWriteRemoteFile);
        }

        /// <summary>
        /// 异步上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        public void UploadFileAsync(string localFullPath, string remoteFileName)
        {
            UploadFileAsync(localFullPath, remoteFileName, false);
        }

        /// <summary>
        /// 异步上传文件到FTP服务器
        /// </summary>
        /// <param name="localFullPath">本地带有完整路径的文件名</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        /// <param name="overWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param>
        public void UploadFileAsync(string localFullPath, string remoteFileName, bool overWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName) || !IsValidFileChars(Path.GetFileName(localFullPath))
                                                      || !IsValidPathChars(Path.GetDirectoryName(localFullPath)))
                {
                    throw new Exception("非法文件名或目录名!");
                }

                if (!overWriteRemoteFile && FileExist(remoteFileName))
                {
                    throw new Exception("FTP服务上面已经存在同名文件！");
                }

                if (File.Exists(localFullPath))
                {
                    MyWebClient client = new MyWebClient();

                    client.UploadProgressChanged += new UploadProgressChangedEventHandler(this.ClientUploadProgressChanged);
                    client.UploadFileCompleted += new UploadFileCompletedEventHandler(this.ClientUploadFileCompleted);
                    client.Credentials = new NetworkCredential(this.UserName, this.Password);
                    if (this.Proxy != null)
                    {
                        client.Proxy = this.Proxy;
                    }

                    client.UploadFileAsync(new Uri(this.Uri.ToString() + remoteFileName), localFullPath);
                }
                else
                {
                    throw new Exception("本地文件不存在!");
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 异步上传文件到FTP服务器
        /// </summary>
        /// <param name="fileBytes">上传的二进制数据</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        public void UploadFileAsync(byte[] fileBytes, string remoteFileName)
        {
            if (!IsValidFileChars(remoteFileName))
            {
                throw new Exception("非法文件名或目录名!");
            }

            UploadFileAsync(fileBytes, remoteFileName, false);
        }

        /// <summary>
        /// 异步上传文件到FTP服务器
        /// </summary>
        /// <param name="fileBytes">文件二进制内容</param>
        /// <param name="remoteFileName">要在FTP服务器上面保存文件名</param>
        /// <param name="overWriteRemoteFile">是否覆盖远程服务器上面同名的文件</param>
        public void UploadFileAsync(byte[] fileBytes, string remoteFileName, bool overWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName))
                {
                    throw new Exception("非法文件名！");
                }

                if (!overWriteRemoteFile && FileExist(remoteFileName))
                {
                    throw new Exception("FTP服务上面已经存在同名文件！");
                }

                string tempPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Templates);
                if (!tempPath.EndsWith("\\"))
                {
                    tempPath += "\\";
                }

                string tempFile = tempPath + Path.GetRandomFileName();
                tempFile = Path.ChangeExtension(tempFile, Path.GetExtension(remoteFileName));
                FileStream stream = new FileStream(tempFile, FileMode.CreateNew, FileAccess.Write);
                stream.Write(fileBytes, 0, fileBytes.Length); ////注意，因为Int32的最大限制，最大上传文件只能是大约2G多一点
                stream.Flush();
                stream.Close();
                stream.Dispose();
                isDeleteTempFile = true;
                strUploadTempFile = tempFile;
                fileBytes = null;
                UploadFileAsync(tempFile, remoteFileName, overWriteRemoteFile);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 异步上传文件完成之后触发的事件
        /// </summary>
        /// <param name="sender">下载对象</param>
        /// <param name="e">数据信息对象</param>
        public void ClientUploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
        {
            if (isDeleteTempFile)
            {
                if (File.Exists(strUploadTempFile))
                {
                    File.SetAttributes(strUploadTempFile, FileAttributes.Normal);
                    File.Delete(strUploadTempFile);
                }

                isDeleteTempFile = false;
            }

            if (UploadFileCompleted != null)
            {
                UploadFileCompleted(sender, e);
            }
        }

        /// <summary>
        /// 异步上传进度发生改变触发的事件
        /// </summary>
        /// <param name="sender">下载对象</param>
        /// <param name="e">进度信息对象</param>
        public void ClientUploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
        {
            if (UploadProgressChanged != null)
            {
                UploadProgressChanged(sender, e);
            }
        }

        #endregion

        #region 列出目录文件信息

        /// <summary>
        /// 列出FTP服务器上面当前目录的所有文件和目录
        /// </summary>
        /// <returns>FileStruct[].</returns>
        public FileStruct[] ListFilesAndDirectories()
        {
            response = Open(this.Uri, WebRequestMethods.Ftp.ListDirectoryDetails);
            using (StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
            {
                string datastring = stream.ReadToEnd();
                FileStruct[] list = GetList(datastring);
                return list;
            }
        }

        /// <summary>
        /// 列出FTP服务器上面当前目录的所有文件和目录
        /// </summary>
        /// <returns>FileStruct[].</returns>
        public FileStruct[] ListFilesAndDirectories(string path)
        {
            response = Open(new Uri(this.Uri.ToString().TrimEnd('/') + "/" + path), WebRequestMethods.Ftp.ListDirectoryDetails);
            StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
            string datastring = stream.ReadToEnd();
            FileStruct[] list = GetList(datastring);
            return list;
        }

        /// <summary>
        /// 列出FTP服务器上面当前目录的所有文件
        /// </summary>
        /// <returns>FileStruct[].</returns>
        public FileStruct[] ListFiles()
        {
            FileStruct[] listAll = ListFilesAndDirectories();
            List<FileStruct> listFile = new List<FileStruct>();
            foreach (FileStruct file in listAll)
            {
                if (!file.IsDirectory)
                {
                    listFile.Add(file);
                }
            }

            return listFile.ToArray();
        }

        /// <summary>
        /// 列出FTP服务器上面当前目录的所有的目录
        /// </summary>
        /// <returns>FileStruct[].</returns>
        public FileStruct[] ListDirectories()
        {
            FileStruct[] listAll = ListFilesAndDirectories();
            List<FileStruct> listDirectory = new List<FileStruct>();
            foreach (FileStruct file in listAll)
            {
                if (file.IsDirectory)
                {
                    listDirectory.Add(file);
                }
            }

            return listDirectory.ToArray();
        }
        /// <summary>
        /// 列出FTP服务器上面当前目录的所有的目录
        /// </summary>
        /// <returns>FileStruct[].</returns>
        public FileStruct[] ListDirectories(string path)
        {
            FileStruct[] listAll = ListFilesAndDirectories(path);
            List<FileStruct> listDirectory = new List<FileStruct>();
            foreach (FileStruct file in listAll)
            {
                if (file.IsDirectory)
                {
                    listDirectory.Add(file);
                }
            }

            return listDirectory.ToArray();
        }
        #endregion

        #region 目录或文件存在的判断

        /// <summary>
        /// 判断当前目录下指定的子目录是否存在
        /// </summary>
        /// <param name="remoteDirectoryName">指定的目录名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">目录名非法！</exception>
        public bool DirectoryExist(string remoteDirectoryName)
        {
            try
            {
                if (!IsValidPathChars(remoteDirectoryName))
                {
                    throw new Exception("目录名非法！");
                }

                FileStruct[] listDir = ListDirectories();
                foreach (FileStruct dir in listDir)
                {
                    if (dir.Name == remoteDirectoryName)
                    {
                        return true;
                    }
                }

                return false;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 判断当前目录下指定的子目录是否存在
        /// </summary>
        /// <param name="remoteDirectoryName">指定的目录名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">目录名非法！</exception>
        public bool DirectoryExist(string parentPath, string remoteDirectoryName)
        {
            try
            {
                if (!IsValidPathChars(remoteDirectoryName))
                {
                    throw new Exception("目录名非法！");
                }

                FileStruct[] listDir = ListDirectories(parentPath);
                foreach (FileStruct dir in listDir)
                {
                    if (dir.Name == remoteDirectoryName)
                    {
                        return true;
                    }
                }

                return false;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 判断一个远程文件是否存在服务器当前目录下面
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">文件名非法！</exception>
        public bool FileExist(string remoteFileName)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName))
                {
                    throw new Exception("文件名非法！");
                }

                FileStruct[] listFile = ListFiles();
                foreach (FileStruct file in listFile)
                {
                    if (file.Name == remoteFileName)
                    {
                        return true;
                    }
                }

                return false;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion

        #region 删除文件

        /// <summary>
        /// 从FTP服务器上面删除一个文件
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        public void DeleteFile(string remoteFileName)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName))
                {
                    throw new Exception("文件名非法！");
                }

                response = Open(new Uri(this.Uri.ToString() + remoteFileName), WebRequestMethods.Ftp.DeleteFile);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 从FTP服务器上面删除一个文件
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        public void DeleteFileByUrl(string remoteFileUrl)
        {
            try
            {
                if (string.IsNullOrEmpty(remoteFileUrl))
                {
                    throw new Exception("文件名非法！");
                }

                response = Open(new Uri(remoteFileUrl), WebRequestMethods.Ftp.DeleteFile);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        #endregion

        #region 重命名文件

        /// <summary>
        /// 更改一个文件的名称或一个目录的名称
        /// </summary>
        /// <param name="remoteFileName">原始文件或目录名称</param>
        /// <param name="newFileName">新的文件或目录的名称</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">
        /// 文件名非法！
        /// or
        /// 文件在服务器上不存在！
        /// </exception>
        public bool ReName(string remoteFileName, string newFileName)
        {
            try
            {
                if (!IsValidFileChars(remoteFileName) || !IsValidFileChars(newFileName))
                {
                    throw new Exception("文件名非法！");
                }

                if (remoteFileName == newFileName)
                {
                    return true;
                }

                if (FileExist(remoteFileName))
                {
                    request = OpenRequest(new Uri(this.Uri.ToString() + remoteFileName), WebRequestMethods.Ftp.Rename);
                    request.RenameTo = newFileName;
                    response = (FtpWebResponse)request.GetResponse();
                }
                else
                {
                    throw new Exception("文件在服务器上不存在！");
                }

                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        #endregion

        #region 拷贝、移动文件
        /// <summary>
        /// 把当前目录下面的一个文件拷贝到服务器上面另外的目录中，注意，拷贝文件之后，当前工作目录还是文件原来所在的目录
        /// </summary>
        /// <param name="remoteFile">当前目录下的文件名</param>
        /// <param name="directoryName">新目录名称。
        /// 说明：如果新目录是当前目录的子目录，则直接指定子目录。如: SubDirectory1/SubDirectory2 ；
        /// 如果新目录不是当前目录的子目录，则必须从根目录一级一级的指定。如： ./NewDirectory/SubDirectory1/SubDirectory2
        /// </param>
        /// <returns></returns>
        public bool CopyFileToAnotherDirectory(string remoteFile, string directoryName)
        {
            string currentWorkDir = this.DirectoryPath;
            try
            {
                byte[] bt = DownloadFile(remoteFile);
                GotoDirectory(directoryName);
                bool success = UploadFile(bt, remoteFile, false);
                this.DirectoryPath = currentWorkDir;
                return success;
            }
            catch (Exception ep)
            {
                this.DirectoryPath = currentWorkDir;
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 把当前目录下面的一个文件移动到服务器上面另外的目录中，注意，移动文件之后，当前工作目录还是文件原来所在的目录
        /// </summary>
        /// <param name="remoteFile">当前目录下的文件名</param>
        /// <param name="directoryName">新目录名称。
        /// 说明：如果新目录是当前目录的子目录，则直接指定子目录。如: SubDirectory1/SubDirectory2 ；
        /// 如果新目录不是当前目录的子目录，则必须从根目录一级一级的指定。如： ./NewDirectory/SubDirectory1/SubDirectory2
        /// </param>
        /// <returns></returns>
        public bool MoveFileToAnotherDirectory(string remoteFile, string directoryName)
        {
            string currentWorkDir = this.DirectoryPath;
            try
            {
                if (directoryName == String.Empty)
                    return false;
                if (!directoryName.StartsWith("/"))
                    directoryName = "/" + directoryName;
                if (!directoryName.EndsWith("/"))
                    directoryName += "/";
                bool success = ReName(remoteFile, directoryName + remoteFile);
                this.DirectoryPath = currentWorkDir;
                return success;
            }
            catch (Exception ep)
            {
                this.DirectoryPath = currentWorkDir;
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        #endregion

        #region 建立、删除子目录

        /// <summary>
        /// 在FTP服务器上当前工作目录建立一个子目录
        /// </summary>
        /// <param name="directoryName">子目录名称</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">
        /// 目录名非法！
        /// or
        /// 服务器上面已经存在同名的文件名或目录名！
        /// </exception>
        public bool MakeDirectory(string directoryName)
        {
            try
            {
                if (!IsValidPathChars(directoryName))
                {
                    throw new Exception("目录名非法！");
                }

                if (DirectoryExist(directoryName))
                {
                    throw new Exception("服务器上面已经存在同名的文件名或目录名！");
                }

                response = Open(new Uri(this.Uri.ToString() + directoryName), WebRequestMethods.Ftp.MakeDirectory);
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 创建多级目录
        /// </summary>
        /// <param name="dirName"></param>
        /// <returns></returns>
        public bool MakeMulDirectory(string dirPathName)
        {
            try
            {
                string[] dirs = dirPathName.Trim().Split('/');
                string tempPath = "";
                for (int i = 0; i < dirs.Length; i++)
                {
                    if (string.IsNullOrEmpty(dirs[i]))
                        continue;
                    var dirName = dirs[i];
                    if (!IsValidPathChars(dirName))
                    {
                        throw new Exception("目录名非法！");
                    }
                    if (DirectoryExist(tempPath, dirName))
                    {
                        tempPath = i > 0 ? tempPath + "/" + dirName : dirName;
                        continue;
                    }
                    tempPath = i > 0 ? tempPath + "/" + dirName : dirName;
                    response = Open(new Uri(this.Uri.ToString() + tempPath), WebRequestMethods.Ftp.MakeDirectory);
                }
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 从当前工作目录中删除一个子目录
        /// </summary>
        /// <param name="directoryName">子目录名称</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">
        /// 目录名非法！
        /// or
        /// 服务器上面不存在指定的文件名或目录名！
        /// </exception>
        public bool RemoveDirectory(string directoryName)
        {
            try
            {
                if (!IsValidPathChars(directoryName))
                {
                    throw new Exception("目录名非法！");
                }

                if (!DirectoryExist(directoryName))
                {
                    throw new Exception("服务器上面不存在指定的文件名或目录名！");
                }

                response = Open(new Uri(this.Uri.ToString() + directoryName), WebRequestMethods.Ftp.RemoveDirectory);
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        #endregion

        #region 文件、目录名称有效性判断

        /// <summary>
        /// 判断目录名中字符是否合法
        /// </summary>
        /// <param name="directoryName">目录名称</param>
        /// <returns><c>true</c> if [is valid path chars] [the specified directory name]; otherwise, <c>false</c>.</returns>
        public bool IsValidPathChars(string directoryName)
        {
            char[] invalidPathChars = Path.GetInvalidPathChars();
            char[] dirChar = directoryName.ToCharArray();
            foreach (char c in dirChar)
            {
                if (Array.BinarySearch(invalidPathChars, c) >= 0)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 判断文件名中字符是否合法
        /// </summary>
        /// <param name="fileName">文件名称</param>
        /// <returns><c>true</c> if [is valid file chars] [the specified file name]; otherwise, <c>false</c>.</returns>
        public bool IsValidFileChars(string fileName)
        {
            char[] invalidFileChars = Path.GetInvalidFileNameChars();
            char[] nameChar = fileName.ToCharArray();
            foreach (char c in nameChar)
            {
                if (Array.BinarySearch(invalidFileChars, c) >= 0)
                {
                    return false;
                }
            }

            return true;
        }

        #endregion

        #region 目录切换操作

        /// <summary>
        /// 进入一个目录
        /// </summary>
        /// <param name="directoryName">新目录的名字。
        /// 说明：如果新目录是当前目录的子目录，则直接指定子目录。如: SubDirectory1/SubDirectory2 ；
        /// 如果新目录不是当前目录的子目录，则必须从根目录一级一级的指定。如： ./NewDirectory/SubDirectory1/SubDirectory2</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        public bool GotoDirectory(string directoryName)
        {
            string currentWorkPath = this.DirectoryPath;
            try
            {
                directoryName = directoryName.Replace("\\", "/");
                string[] directoryNames = directoryName.Split(new char[] { '/' });
                if (directoryNames[0] == ".")
                {
                    this.DirectoryPath = "/";
                    if (directoryNames.Length == 1)
                    {
                        return true;
                    }

                    Array.Clear(directoryNames, 0, 1);
                }

                bool success = false;
                foreach (string dir in directoryNames)
                {
                    if (dir != null)
                    {
                        success = EnterOneSubDirectory(dir);
                        if (!success)
                        {
                            this.DirectoryPath = currentWorkPath;
                            return false;
                        }
                    }
                }

                return success;
            }
            catch (Exception ex)
            {
                this.DirectoryPath = currentWorkPath;
                ErrorMsg = ex.ToString();
                throw ex;
            }
        }

        /// <summary>
        /// 从当前工作目录往上一级目录
        /// </summary>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">当前目录已经是根目录！</exception>
        public bool ComeoutDirectory()
        {
            if (directoryPath == "/")
            {
                ErrorMsg = "当前目录已经是根目录！";
                throw new Exception("当前目录已经是根目录！");
            }

            char[] sp = new char[1] { '/' };

            string[] strDir = directoryPath.Split(sp, StringSplitOptions.RemoveEmptyEntries);
            if (strDir.Length == 1)
            {
                directoryPath = "/";
            }
            else
            {
                directoryPath = String.Join("/", strDir, 0, strDir.Length - 1);
            }

            return true;
        }

        #endregion

        #region 建立连接
        /// <summary>
        /// 从当前工作目录进入一个子目录
        /// </summary>
        /// <param name="directoryName">子目录名称</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        /// <exception cref="Exception">目录名非法!</exception>
        private bool EnterOneSubDirectory(string directoryName)
        {
            try
            {
                if (directoryName.IndexOf("/") >= 0 || !IsValidPathChars(directoryName))
                {
                    throw new Exception("目录名非法!");
                }

                if (directoryName.Length > 0 && DirectoryExist(directoryName))
                {
                    if (!directoryName.EndsWith("/"))
                    {
                        directoryName += "/";
                    }

                    directoryPath += directoryName;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                ErrorMsg = ex.ToString();
                throw ex;
            }
        }

        /// <summary>
        /// 建立FTP链接,返回响应对象
        /// </summary>
        /// <param name="uri">FTP地址</param>
        /// <param name="myFtpMethod">操作命令</param>
        /// <returns>FtpWebResponse.</returns>
        private FtpWebResponse Open(Uri uri, string myFtpMethod)
        {
            try
            {
                request = (FtpWebRequest)WebRequest.Create(uri);
                request.Method = myFtpMethod;
                request.UseBinary = true;
                request.Credentials = new NetworkCredential(this.UserName, this.Password);
                if (this.Proxy != null)
                {
                    request.Proxy = this.Proxy;
                }

                return (FtpWebResponse)request.GetResponse();
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 建立FTP链接,返回请求对象
        /// </summary>
        /// <param name="uri">FTP地址</param>
        /// <param name="ftpMathod">操作命令</param>
        /// <returns>FtpWebRequest.</returns>
        private FtpWebRequest OpenRequest(Uri uri, string ftpMathod)
        {
            try
            {
                request = (FtpWebRequest)WebRequest.Create(uri);
                request.Method = ftpMathod;
                request.UseBinary = true;
                request.Credentials = new NetworkCredential(this.UserName, this.Password);
                if (this.Proxy != null)
                {
                    request.Proxy = this.Proxy;
                }

                return request;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 获得文件和目录列表
        /// </summary>
        /// <param name="datastring">FTP返回的列表字符信息</param>
        /// <returns>FileStruct[].</returns>
        private FileStruct[] GetList(string datastring)
        {
            List<FileStruct> myListArray = new List<FileStruct>();
            string[] dataRecords = datastring.Split('\n');
            FileListStyle directoryListStyle = GuessFileListStyle(dataRecords);
            foreach (string s in dataRecords)
            {
                if (directoryListStyle != FileListStyle.Unknown && s != String.Empty)
                {
                    FileStruct f = new FileStruct();
                    f.Name = "..";
                    switch (directoryListStyle)
                    {
                        case FileListStyle.UnixStyle:
                            f = ParseFileStructFromUnixStyleRecord(s);
                            break;
                        case FileListStyle.WindowsStyle:
                            f = ParseFileStructFromWindowsStyleRecord(s);
                            break;
                    }

                    if (!(f.Name == "." || f.Name == ".."))
                    {
                        myListArray.Add(f);
                    }
                }
            }

            return myListArray.ToArray();
        }

        /// <summary>
        /// 从Windows格式中返回文件信息
        /// </summary>
        /// <param name="record">文件信息</param>
        /// <returns>FileStruct.</returns>
        private FileStruct ParseFileStructFromWindowsStyleRecord(string record)
        {
            FileStruct f = new FileStruct();
            string processstr = record.Trim();
            string dateStr = processstr.Substring(0, 8);
            processstr = processstr.Substring(8, processstr.Length - 8).Trim();
            string timeStr = processstr.Substring(0, 7);
            processstr = processstr.Substring(7, processstr.Length - 7).Trim();
            DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat;
            myDTFI.ShortTimePattern = "t";
            f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI);
            if (processstr.Substring(0, 5) == "<DIR>")
            {
                f.IsDirectory = true;
                processstr = processstr.Substring(5, processstr.Length - 5).Trim();
            }
            else
            {
                string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // true);
                processstr = strs[1];
                f.IsDirectory = false;
            }

            f.Name = processstr;
            return f;
        }

        /// <summary>
        /// 判断文件列表的方式Window方式还是Unix方式
        /// </summary>
        /// <param name="recordList">文件信息列表</param>
        /// <returns>FileListStyle.</returns>
        private FileListStyle GuessFileListStyle(string[] recordList)
        {
            foreach (string s in recordList)
            {
                if (s.Length > 10 && Regex.IsMatch(
                        s.Substring(0, 10),
                        "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)"))
                {
                    return FileListStyle.UnixStyle;
                }
                else if (s.Length > 8 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]"))
                {
                    return FileListStyle.WindowsStyle;
                }
            }

            return FileListStyle.Unknown;
        }

        /// <summary>
        /// 从Unix格式中返回文件信息
        /// </summary>
        /// <param name="record">文件信息</param>
        /// <returns>FileStruct.</returns>
        private FileStruct ParseFileStructFromUnixStyleRecord(string record)
        {
            FileStruct f = new FileStruct();
            string processstr = record.Trim();
            f.Flags = processstr.Substring(0, 10);
            f.IsDirectory = f.Flags[0] == 'd';
            processstr = processstr.Substring(11).Trim();
            _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); // 跳过一部分
            f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            string size= _cutSubstringFromStringWithTrim(ref processstr, ' ', 0); // 跳过一部分
            int.TryParse(size, out f.FileSize);
            string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2];
            if (yearOrTime.IndexOf(":") >= 0)
            {
                processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString());
            }

            f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8));
            f.Name = processstr; // 最后就是名称
            return f;
        }

        /// <summary>
        /// 按照一定的规则进行字符串截取
        /// </summary>
        /// <param name="s">截取的字符串</param>
        /// <param name="c">查找的字符</param>
        /// <param name="startIndex">查找的位置</param>
        /// <returns>System.String.</returns>
        private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex)
        {
            int pos1 = s.IndexOf(c, startIndex);
            string retString = s.Substring(0, pos1);
            s = s.Substring(pos1).Trim();
            return retString;
        }

        #endregion

        #region 重载WebClient，支持FTP进度

        /// <summary>
        /// Class MyWebClient.
        /// </summary>
        /// <seealso cref="System.Net.WebClient" />
        internal class MyWebClient : WebClient
        {
            /// <summary>
            /// 为指定资源返回一个 <see cref="T:System.Net.WebRequest" /> 对象。
            /// </summary>
            /// <param name="address">一个 <see cref="T:System.Uri" />，用于标识要请求的资源。</param>
            /// <returns>一个新的 <see cref="T:System.Net.WebRequest" /> 对象，用于指定的资源。</returns>
            protected override WebRequest GetWebRequest(Uri address)
            {
                FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address);
                req.UsePassive = false;
                return req;
            }
        }
        #endregion
    }
}